home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / sh.set.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  18.4 KB  |  919 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/sh.set.c,v 3.18 1992/10/05 02:41:30 christos Exp $ */
  2. /*
  3.  * sh.set.c: Setting and Clearing of variables
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: sh.set.c,v 3.18 1992/10/05 02:41:30 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "tw.h"
  43.  
  44. extern Char HistLit;
  45. extern bool GotTermCaps;
  46.  
  47. static    void         update_vars    __P((Char *));
  48. static    Char        *getinx        __P((Char *, int *));
  49. static    void         asx        __P((Char *, int, Char *));
  50. static    struct varent     *getvx        __P((Char *, int));
  51. static    Char        *xset        __P((Char *, Char ***));
  52. static    Char        *operate    __P((int, Char *, Char *));
  53. static    void          putn1        __P((int));
  54. static    struct varent    *madrof        __P((Char *, struct varent *));
  55. static    void         unsetv1    __P((struct varent *));
  56. static    void         exportpath    __P((Char **));
  57. static    void         balance    __P((struct varent *, int, int));
  58.  
  59. /*
  60.  * C Shell
  61.  */
  62.  
  63. static void
  64. update_vars(vp)
  65.     Char *vp;
  66. {
  67.     if (eq(vp, STRpath)) {
  68.     exportpath(adrof(STRpath)->vec);
  69.     dohash(NULL, NULL);
  70.     }
  71.     else if (eq(vp, STRhistchars)) {
  72.     register Char *pn = value(vp);
  73.  
  74.     HIST = *pn++;
  75.     HISTSUB = *pn;
  76.     }
  77.     else if (eq(vp, STRhistlit)) {
  78.     HistLit = 1;
  79.     }
  80.     else if (eq(vp, STRuser)) {
  81.     tsetenv(STRKUSER, value(vp));
  82.     tsetenv(STRLOGNAME, value(vp));
  83.     }
  84.     else if (eq(vp, STRwordchars)) {
  85.     word_chars = value(vp);
  86.     }
  87.     else if (eq(vp, STRsymlinks)) {
  88.     register Char *pn = value(vp);
  89.  
  90.     if (eq(pn, STRignore))
  91.         symlinks = SYM_IGNORE;
  92.     else if (eq(pn, STRexpand))
  93.         symlinks = SYM_EXPAND;
  94.     else if (eq(pn, STRchase))
  95.         symlinks = SYM_CHASE;
  96.     else
  97.         symlinks = 0;
  98.     }
  99.     else if (eq(vp, STRterm)) {
  100. #ifdef DOESNT_WORK_RIGHT
  101.     register Char *cp;
  102. #endif /* DOESNT_WORK_RIGHT */
  103.     tsetenv(STRKTERM, value(vp));
  104. #ifdef DOESNT_WORK_RIGHT
  105.     cp = getenv("TERMCAP");
  106.     if (cp && (*cp != '/'))    /* if TERMCAP and not a path */
  107.         Unsetenv(STRTERMCAP);
  108. #endif /* DOESNT_WORK_RIGHT */
  109.     GotTermCaps = 0;
  110.     ed_Init();        /* reset the editor */
  111.     }
  112.     else if (eq(vp, STRhome)) {
  113.     register Char *cp;
  114.  
  115.     cp = Strsave(value(vp));    /* get the old value back */
  116.  
  117.     /*
  118.      * convert to cononical pathname (possibly resolving symlinks)
  119.      */
  120.     cp = dcanon(cp, cp);
  121.  
  122.     set(vp, Strsave(cp));    /* have to save the new val */
  123.  
  124.     /* and now mirror home with HOME */
  125.     tsetenv(STRKHOME, cp);
  126.     /* fix directory stack for new tilde home */
  127.     dtilde();
  128.     xfree((ptr_t) cp);
  129.     }
  130.     else if (eq(vp, STRedit)) {
  131.     editing = 1;
  132.     /* PWP: add more stuff in here later */
  133.     }
  134.     else if (eq(vp, STRshlvl)) {
  135.     tsetenv(STRKSHLVL, value(vp));
  136.     }
  137.     else if (eq(vp, STRbackslash_quote)) {
  138.     bslash_quote = 1;
  139.     }
  140.     else if (eq(vp, STRdirstack)) {
  141.     dsetstack();
  142.     }
  143.     else if (eq(vp, STRrecognize_only_executables)) {
  144.     tw_cmd_free();
  145.     }
  146. #ifndef HAVENOUTMP
  147.     else if (eq(vp, STRwatch)) {
  148.     resetwatch();
  149.     }
  150. #endif /* HAVENOUTMP */
  151. }
  152.  
  153.  
  154. /*ARGSUSED*/
  155. void
  156. doset(v, c)
  157.     register Char **v;
  158.     struct command *c;
  159. {
  160.     register Char *p;
  161.     Char   *vp, op;
  162.     Char  **vecp;
  163.     bool    hadsub;
  164.     int     subscr;
  165.  
  166.     v++;
  167.     p = *v++;
  168.     if (p == 0) {
  169.     prvars();
  170.     return;
  171.     }
  172.     do {
  173.     hadsub = 0;
  174.     vp = p;
  175.     if (letter(*p))
  176.         for (; alnum(*p); p++)
  177.         continue;
  178.     if (vp == p || !letter(*vp))
  179.         stderror(ERR_NAME | ERR_VARBEGIN);
  180.     if ((p - vp) > MAXVARLEN) {
  181.         stderror(ERR_NAME | ERR_VARTOOLONG);
  182.         return;
  183.     }
  184.     if (*p == '[') {
  185.         hadsub++;
  186.         p = getinx(p, &subscr);
  187.     }
  188.     if ((op = *p) != 0) {
  189.         *p++ = 0;
  190.         if (*p == 0 && *v && **v == '(')
  191.         p = *v++;
  192.     }
  193.     else if (*v && eq(*v, STRequal)) {
  194.         op = '=', v++;
  195.         if (*v)
  196.         p = *v++;
  197.     }
  198.     if (op && op != '=')
  199.         stderror(ERR_NAME | ERR_SYNTAX);
  200.     if (eq(p, STRLparen)) {
  201.         register Char **e = v;
  202.  
  203.         if (hadsub)
  204.         stderror(ERR_NAME | ERR_SYNTAX);
  205.         for (;;) {
  206.         if (!*e)
  207.             stderror(ERR_NAME | ERR_MISSING, ')');
  208.         if (**e == ')')
  209.             break;
  210.         e++;
  211.         }
  212.         p = *e;
  213.         *e = 0;
  214.         vecp = saveblk(v);
  215.         set1(vp, vecp, &shvhed);
  216.         *e = p;
  217.         v = e + 1;
  218.     }
  219.     else if (hadsub)
  220.         asx(vp, subscr, Strsave(p));
  221.     else
  222.         set(vp, Strsave(p));
  223.     update_vars(vp);
  224.     } while ((p = *v++) != NULL);
  225. }
  226.  
  227. static Char *
  228. getinx(cp, ip)
  229.     register Char *cp;
  230.     register int *ip;
  231. {
  232.     *ip = 0;
  233.     *cp++ = 0;
  234.     while (*cp && Isdigit(*cp))
  235.     *ip = *ip * 10 + *cp++ - '0';
  236.     if (*cp++ != ']')
  237.     stderror(ERR_NAME | ERR_SUBSCRIPT);
  238.     return (cp);
  239. }
  240.  
  241. static void
  242. asx(vp, subscr, p)
  243.     Char   *vp;
  244.     int     subscr;
  245.     Char   *p;
  246. {
  247.     register struct varent *v = getvx(vp, subscr);
  248.  
  249.     xfree((ptr_t) v->vec[subscr - 1]);
  250.     v->vec[subscr - 1] = globone(p, G_APPEND);
  251. }
  252.  
  253. static struct varent *
  254. getvx(vp, subscr)
  255.     Char   *vp;
  256.     int     subscr;
  257. {
  258.     register struct varent *v = adrof(vp);
  259.  
  260.     if (v == 0)
  261.     udvar(vp);
  262.     if (subscr < 1 || subscr > blklen(v->vec))
  263.     stderror(ERR_NAME | ERR_RANGE);
  264.     return (v);
  265. }
  266.  
  267. /*ARGSUSED*/
  268. void
  269. dolet(v, dummy)
  270.     Char  **v;
  271.     struct command *dummy;
  272. {
  273.     register Char *p;
  274.     Char   *vp, c, op;
  275.     bool    hadsub;
  276.     int     subscr;
  277.  
  278.     v++;
  279.     p = *v++;
  280.     if (p == 0) {
  281.     prvars();
  282.     return;
  283.     }
  284.     do {
  285.     hadsub = 0;
  286.     vp = p;
  287.     if (letter(*p))
  288.         for (; alnum(*p); p++)
  289.         continue;
  290.     if (vp == p || !letter(*vp))
  291.         stderror(ERR_NAME | ERR_VARBEGIN);
  292.     if ((p - vp) > MAXVARLEN)
  293.         stderror(ERR_NAME | ERR_VARTOOLONG);
  294.     if (*p == '[') {
  295.         hadsub++;
  296.         p = getinx(p, &subscr);
  297.     }
  298.     if (*p == 0 && *v)
  299.         p = *v++;
  300.     if ((op = *p) != 0)
  301.         *p++ = 0;
  302.     else
  303.         stderror(ERR_NAME | ERR_ASSIGN);
  304.  
  305.     /*
  306.      * if there is no expression after the '=' then print a "Syntax Error"
  307.      * message - strike
  308.      */
  309.     if (*p == '\0' && *v == NULL)
  310.         stderror(ERR_NAME | ERR_ASSIGN);
  311.  
  312.     vp = Strsave(vp);
  313.     if (op == '=') {
  314.         c = '=';
  315.         p = xset(p, &v);
  316.     }
  317.     else {
  318.         c = *p++;
  319.         if (any("+-", c)) {
  320.         if (c != op || *p)
  321.             stderror(ERR_NAME | ERR_UNKNOWNOP);
  322.         p = Strsave(STR1);
  323.         }
  324.         else {
  325.         if (any("<>", op)) {
  326.             if (c != op)
  327.             stderror(ERR_NAME | ERR_UNKNOWNOP);
  328.             c = *p++;
  329.             stderror(ERR_NAME | ERR_SYNTAX);
  330.         }
  331.         if (c != '=')
  332.             stderror(ERR_NAME | ERR_UNKNOWNOP);
  333.         p = xset(p, &v);
  334.         }
  335.     }
  336.     if (op == '=')
  337.         if (hadsub)
  338.         asx(vp, subscr, p);
  339.         else
  340.         set(vp, p);
  341.     else if (hadsub) {
  342.         struct varent *gv = getvx(vp, subscr);
  343.  
  344.         asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
  345.     }
  346.     else
  347.         set(vp, operate(op, value(vp), p));
  348.     update_vars(vp);
  349.     xfree((ptr_t) vp);
  350.     if (c != '=')
  351.         xfree((ptr_t) p);
  352.     } while ((p = *v++) != NULL);
  353. }
  354.  
  355. static Char *
  356. xset(cp, vp)
  357.     Char   *cp, ***vp;
  358. {
  359.     register Char *dp;
  360.  
  361.     if (*cp) {
  362.     dp = Strsave(cp);
  363.     --(*vp);
  364.     xfree((ptr_t) ** vp);
  365.     **vp = dp;
  366.     }
  367.     return (putn(expr(vp)));
  368. }
  369.  
  370. static Char *
  371. operate(op, vp, p)
  372.     int     op;
  373.     Char    *vp, *p;
  374. {
  375.     Char    opr[2];
  376.     Char   *vec[5];
  377.     register Char **v = vec;
  378.     Char  **vecp = v;
  379.     register int i;
  380.  
  381.     if (op != '=') {
  382.     if (*vp)
  383.         *v++ = vp;
  384.     opr[0] = op;
  385.     opr[1] = 0;
  386.     *v++ = opr;
  387.     if (op == '<' || op == '>')
  388.         *v++ = opr;
  389.     }
  390.     *v++ = p;
  391.     *v++ = 0;
  392.     i = expr(&vecp);
  393.     if (*vecp)
  394.     stderror(ERR_NAME | ERR_EXPRESSION);
  395.     return (putn(i));
  396. }
  397.  
  398. static Char *putp, nbuf[50];
  399.  
  400. Char   *
  401. putn(n)
  402.     register int n;
  403. {
  404.     int     num;
  405.  
  406.     putp = nbuf;
  407.     if (n < 0) {
  408.     n = -n;
  409.     *putp++ = '-';
  410.     }
  411.     num = 2;            /* confuse lint */
  412.     if (sizeof(int) == num && ((unsigned int) n) == 32768) {
  413.     *putp++ = '3';
  414.     n = 2768;
  415. #ifdef pdp11
  416.     }
  417. #else /* !pdp11 */
  418.     }
  419.     else {
  420.     num = 4;        /* confuse lint */
  421.     if (sizeof(int) == num && ((unsigned int) n) == 2147483648) {
  422.         *putp++ = '2';
  423.         n = 147483648;
  424.     }
  425.     }
  426. #endif /* pdp11 */
  427.     putn1(n);
  428.     *putp = 0;
  429.     return (Strsave(nbuf));
  430. }
  431.  
  432. static void
  433. putn1(n)
  434.     register int n;
  435. {
  436.     if (n > 9)
  437.     putn1(n / 10);
  438.     *putp++ = n % 10 + '0';
  439. }
  440.  
  441. int
  442. getn(cp)
  443.     register Char *cp;
  444. {
  445.     register int n;
  446.     int     sign;
  447.  
  448.     if (!cp)            /* PWP: extra error checking */
  449.     stderror(ERR_NAME | ERR_BADNUM);
  450.  
  451.     sign = 0;
  452.     if (cp[0] == '+' && cp[1])
  453.     cp++;
  454.     if (*cp == '-') {
  455.     sign++;
  456.     cp++;
  457.     if (!Isdigit(*cp))
  458.         stderror(ERR_NAME | ERR_BADNUM);
  459.     }
  460.     n = 0;
  461.     while (Isdigit(*cp))
  462.     n = n * 10 + *cp++ - '0';
  463.     if (*cp)
  464.     stderror(ERR_NAME | ERR_BADNUM);
  465.     return (sign ? -n : n);
  466. }
  467.  
  468. Char   *
  469. value1(var, head)
  470.     Char   *var;
  471.     struct varent *head;
  472. {
  473.     register struct varent *vp;
  474.  
  475.     if (!var || !head)        /* PWP: extra error checking */
  476.     return (STRNULL);
  477.  
  478.     vp = adrof1(var, head);
  479.     return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
  480. }
  481.  
  482. static struct varent *
  483. madrof(pat, vp)
  484.     Char   *pat;
  485.     register struct varent *vp;
  486. {
  487.     register struct varent *vp1;
  488.  
  489.     for (vp = vp->v_left; vp; vp = vp->v_right) {
  490.     if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
  491.         return vp1;
  492.     if (Gmatch(vp->v_name, pat))
  493.         return vp;
  494.     }
  495.     return vp;
  496. }
  497.  
  498. struct varent *
  499. adrof1(name, v)
  500.     register Char *name;
  501.     register struct varent *v;
  502. {
  503.     register cmp;
  504.  
  505.     v = v->v_left;
  506.     while (v && ((cmp = *name - *v->v_name) != 0 || 
  507.          (cmp = Strcmp(name, v->v_name)) != 0))
  508.     if (cmp < 0)
  509.         v = v->v_left;
  510.     else
  511.         v = v->v_right;
  512.     return v;
  513. }
  514.  
  515. /*
  516.  * The caller is responsible for putting value in a safe place
  517.  */
  518. void
  519. set(var, val)
  520.     Char   *var, *val;
  521. {
  522.     register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
  523.  
  524.     vec[0] = val;
  525.     vec[1] = 0;
  526.     set1(var, vec, &shvhed);
  527. }
  528.  
  529. void
  530. set1(var, vec, head)
  531.     Char   *var, **vec;
  532.     struct varent *head;
  533. {
  534.     register Char **oldv = vec;
  535.  
  536.     gflag = 0;
  537.     tglob(oldv);
  538.     if (gflag) {
  539.     vec = globall(oldv);
  540.     if (vec == 0) {
  541.         blkfree(oldv);
  542.         stderror(ERR_NAME | ERR_NOMATCH);
  543.         return;
  544.     }
  545.     blkfree(oldv);
  546.     gargv = 0;
  547.     }
  548.     setq(var, vec, head);
  549. }
  550.  
  551.  
  552. void
  553. setq(name, vec, p)
  554.     Char   *name, **vec;
  555.     register struct varent *p;
  556. {
  557.     register struct varent *c;
  558.     register f;
  559.  
  560.     f = 0;            /* tree hangs off the header's left link */
  561.     while ((c = p->v_link[f]) != 0) {
  562.     if ((f = *name - *c->v_name) == 0 &&
  563.         (f = Strcmp(name, c->v_name)) == 0) {
  564.         blkfree(c->vec);
  565.         goto found;
  566.     }
  567.     p = c;
  568.     f = f > 0;
  569.     }
  570.     p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
  571.     c->v_name = Strsave(name);
  572.     c->v_bal = 0;
  573.     c->v_left = c->v_right = 0;
  574.     c->v_parent = p;
  575.     balance(p, f, 0);
  576. found:
  577.     trim(c->vec = vec);
  578. }
  579.  
  580. /*ARGSUSED*/
  581. void
  582. unset(v, c)
  583.     Char   **v;
  584.     struct command *c;
  585. {
  586.     bool did_only;
  587.  
  588.     did_only = adrof(STRrecognize_only_executables) != NULL;
  589.     unset1(v, &shvhed);
  590.     if (adrof(STRhistchars) == 0) {
  591.     HIST = '!';
  592.     HISTSUB = '^';
  593.     }
  594.     if (adrof(STRhistlit) == 0)
  595.     HistLit = 0;
  596.     if (adrof(STRwordchars) == 0)
  597.     word_chars = STR_WORD_CHARS;
  598.     if (adrof(STRedit) == 0)
  599.     editing = 0;
  600.     if (adrof(STRbackslash_quote) == 0)
  601.     bslash_quote = 0;
  602.     if (adrof(STRsymlinks) == 0)
  603.     symlinks = 0;
  604.     if (did_only && adrof(STRrecognize_only_executables) == 0)
  605.     tw_cmd_free();
  606. }
  607.  
  608. void
  609. unset1(v, head)
  610.     register Char *v[];
  611.     struct varent *head;
  612. {
  613.     register struct varent *vp;
  614.     register int cnt;
  615.  
  616.     while (*++v) {
  617.     cnt = 0;
  618.     while ((vp = madrof(*v, head)) != NULL)
  619.         unsetv1(vp), cnt++;
  620.     if (cnt == 0)
  621.         setname(short2str(*v));
  622.     }
  623. }
  624.  
  625. void
  626. unsetv(var)
  627.     Char   *var;
  628. {
  629.     register struct varent *vp;
  630.  
  631.     if ((vp = adrof1(var, &shvhed)) == 0)
  632.     udvar(var);
  633.     unsetv1(vp);
  634. }
  635.  
  636. static void
  637. unsetv1(p)
  638.     register struct varent *p;
  639. {
  640.     register struct varent *c, *pp;
  641.     register f;
  642.  
  643.     /*
  644.      * Free associated memory first to avoid complications.
  645.      */
  646.     blkfree(p->vec);
  647.     xfree((ptr_t) p->v_name);
  648.     /*
  649.      * If p is missing one child, then we can move the other into where p is.
  650.      * Otherwise, we find the predecessor of p, which is guaranteed to have no
  651.      * right child, copy it into p, and move it's left child into it.
  652.      */
  653.     if (p->v_right == 0)
  654.     c = p->v_left;
  655.     else if (p->v_left == 0)
  656.     c = p->v_right;
  657.     else {
  658.     for (c = p->v_left; c->v_right; c = c->v_right)
  659.         continue;
  660.     p->v_name = c->v_name;
  661.     p->vec = c->vec;
  662.     p = c;
  663.     c = p->v_left;
  664.     }
  665.  
  666.     /*
  667.      * Move c into where p is.
  668.      */
  669.     pp = p->v_parent;
  670.     f = pp->v_right == p;
  671.     if ((pp->v_link[f] = c) != 0)
  672.     c->v_parent = pp;
  673.     /*
  674.      * Free the deleted node, and rebalance.
  675.      */
  676.     xfree((ptr_t) p);
  677.     balance(pp, f, 1);
  678. }
  679.  
  680. void
  681. setNS(cp)
  682.     Char   *cp;
  683. {
  684.     set(cp, Strsave(STRNULL));
  685. }
  686.  
  687. /*ARGSUSED*/
  688. void
  689. shift(v, c)
  690.     register Char **v;
  691.     struct command *c;
  692. {
  693.     register struct varent *argv;
  694.     register Char *name;
  695.  
  696.     v++;
  697.     name = *v;
  698.     if (name == 0)
  699.     name = STRargv;
  700.     else
  701.     (void) strip(name);
  702.     argv = adrof(name);
  703.     if (argv == 0)
  704.     udvar(name);
  705.     if (argv->vec[0] == 0)
  706.     stderror(ERR_NAME | ERR_NOMORE);
  707.     lshift(argv->vec, 1);
  708.     update_vars(name);
  709. }
  710.  
  711. static Char STRsep[2] = { PATHSEP, '\0' };
  712.  
  713. static void
  714. exportpath(val)
  715.     Char  **val;
  716. {
  717.     Char    exppath[BUFSIZE];
  718.  
  719.     exppath[0] = 0;
  720.     if (val)
  721.     while (*val) {
  722.         if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZE) {
  723.         xprintf("Warning: ridiculously long PATH truncated\n");
  724.         break;
  725.         }
  726.         (void) Strcat(exppath, *val++);
  727.         if (*val == 0 || eq(*val, STRRparen))
  728.         break;
  729.         (void) Strcat(exppath, STRsep);
  730.     }
  731.     tsetenv(STRKPATH, exppath);
  732. }
  733.  
  734. #ifndef lint
  735.  /*
  736.   * Lint thinks these have null effect
  737.   */
  738.  /* macros to do single rotations on node p */
  739. # define rright(p) (\
  740.     t = (p)->v_left,\
  741.     (t)->v_parent = (p)->v_parent,\
  742.     (((p)->v_left = t->v_right) != NULL) ?\
  743.         (t->v_right->v_parent = (p)) : 0,\
  744.     (t->v_right = (p))->v_parent = t,\
  745.     (p) = t)
  746. # define rleft(p) (\
  747.     t = (p)->v_right,\
  748.     ((t)->v_parent = (p)->v_parent,\
  749.     ((p)->v_right = t->v_left) != NULL) ? \
  750.         (t->v_left->v_parent = (p)) : 0,\
  751.     (t->v_left = (p))->v_parent = t,\
  752.     (p) = t)
  753. #else
  754. static struct varent *
  755. rleft(p)
  756.     struct varent *p;
  757. {
  758.     return (p);
  759. }
  760. static struct varent *
  761. rright(p)
  762.     struct varent *p;
  763. {
  764.     return (p);
  765. }
  766.  
  767. #endif /* ! lint */
  768.  
  769.  
  770. /*
  771.  * Rebalance a tree, starting at p and up.
  772.  * F == 0 means we've come from p's left child.
  773.  * D == 1 means we've just done a delete, otherwise an insert.
  774.  */
  775. static void
  776. balance(p, f, d)
  777.     register struct varent *p;
  778.     register int f, d;
  779. {
  780.     register struct varent *pp;
  781.  
  782. #ifndef lint
  783.     register struct varent *t;    /* used by the rotate macros */
  784. #endif /* !lint */
  785.     register int ff;
  786. #ifdef lint
  787.     ff = 0;    /* Sun's lint is dumb! */
  788. #endif
  789.  
  790.     /*
  791.      * Ok, from here on, p is the node we're operating on; pp is it's parent; f
  792.      * is the branch of p from which we have come; ff is the branch of pp which
  793.      * is p.
  794.      */
  795.     for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
  796.     ff = pp->v_right == p;
  797.     if (f ^ d) {        /* right heavy */
  798.         switch (p->v_bal) {
  799.         case -1:        /* was left heavy */
  800.         p->v_bal = 0;
  801.         break;
  802.         case 0:        /* was balanced */
  803.         p->v_bal = 1;
  804.         break;
  805.         case 1:        /* was already right heavy */
  806.         switch (p->v_right->v_bal) {
  807.         case 1:    /* sigle rotate */
  808.             pp->v_link[ff] = rleft(p);
  809.             p->v_left->v_bal = 0;
  810.             p->v_bal = 0;
  811.             break;
  812.         case 0:    /* single rotate */
  813.             pp->v_link[ff] = rleft(p);
  814.             p->v_left->v_bal = 1;
  815.             p->v_bal = -1;
  816.             break;
  817.         case -1:    /* double rotate */
  818.             (void) rright(p->v_right);
  819.             pp->v_link[ff] = rleft(p);
  820.             p->v_left->v_bal =
  821.             p->v_bal < 1 ? 0 : -1;
  822.             p->v_right->v_bal =
  823.             p->v_bal > -1 ? 0 : 1;
  824.             p->v_bal = 0;
  825.             break;
  826.         default:
  827.             break;
  828.         }
  829.         break;
  830.         default:
  831.         break;
  832.         }
  833.     }
  834.     else {            /* left heavy */
  835.         switch (p->v_bal) {
  836.         case 1:        /* was right heavy */
  837.         p->v_bal = 0;
  838.         break;
  839.         case 0:        /* was balanced */
  840.         p->v_bal = -1;
  841.         break;
  842.         case -1:        /* was already left heavy */
  843.         switch (p->v_left->v_bal) {
  844.         case -1:    /* single rotate */
  845.             pp->v_link[ff] = rright(p);
  846.             p->v_right->v_bal = 0;
  847.             p->v_bal = 0;
  848.             break;
  849.         case 0:    /* signle rotate */
  850.             pp->v_link[ff] = rright(p);
  851.             p->v_right->v_bal = -1;
  852.             p->v_bal = 1;
  853.             break;
  854.         case 1:    /* double rotate */
  855.             (void) rleft(p->v_left);
  856.             pp->v_link[ff] = rright(p);
  857.             p->v_left->v_bal =
  858.             p->v_bal < 1 ? 0 : -1;
  859.             p->v_right->v_bal =
  860.             p->v_bal > -1 ? 0 : 1;
  861.             p->v_bal = 0;
  862.             break;
  863.         default:
  864.             break;
  865.         }
  866.         break;
  867.         default:
  868.         break;
  869.         }
  870.     }
  871.     /*
  872.      * If from insert, then we terminate when p is balanced. If from
  873.      * delete, then we terminate when p is unbalanced.
  874.      */
  875.     if ((p->v_bal == 0) ^ d)
  876.         break;
  877.     }
  878. }
  879.  
  880. void
  881. plist(p)
  882.     register struct varent *p;
  883. {
  884.     register struct varent *c;
  885.     register len;
  886.  
  887.     if (setintr)
  888. #ifdef BSDSIGS
  889.     (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
  890. #else /* !BSDSIGS */
  891.     (void) sigrelse(SIGINT);
  892. #endif /* BSDSIGS */
  893.  
  894.     for (;;) {
  895.     while (p->v_left)
  896.         p = p->v_left;
  897. x:
  898.     if (p->v_parent == 0)    /* is it the header? */
  899.         return;
  900.     len = blklen(p->vec);
  901.     xprintf("%S\t", p->v_name);
  902.     if (len != 1)
  903.         xputchar('(');
  904.     blkpr(p->vec);
  905.     if (len != 1)
  906.         xputchar(')');
  907.     xputchar('\n');
  908.     if (p->v_right) {
  909.         p = p->v_right;
  910.         continue;
  911.     }
  912.     do {
  913.         c = p;
  914.         p = p->v_parent;
  915.     } while (p->v_right == c);
  916.     goto x;
  917.     }
  918. }
  919.